package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.UserModelUrl;
import com.zbkj.common.model.product.Product;
import com.zbkj.common.model.product.ProductAttrValue;
import com.zbkj.common.request.AgainGenerateImageRequest;
import com.zbkj.common.request.AiRequest;
import com.zbkj.common.utils.RestTemplateUtil;
import com.zbkj.service.dao.ProductAttrValueDao;
import com.zbkj.service.dao.ProductCategoryDao;
import com.zbkj.service.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ProductAttrValueServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Service
public class ProductAttrValueServiceImpl extends ServiceImpl<ProductAttrValueDao, ProductAttrValue> implements ProductAttrValueService {

    @Resource
    private ProductAttrValueDao dao;
    @Autowired
    private UserModelUrlService userModelUrlService;
    @Autowired
    private ProductService productService;
    @Autowired
    private SystemAttachmentService systemAttachmentService;
    @Autowired
    private ProductCategoryDao productCategoryDao;
    @Autowired
    private RestTemplateUtil restTemplateUtil;


    /**
     * 根据商品id删除AttrValue
     *
     * @param productId 商品id
     * @param type      类型区分是是否添加营销
     * @reture 删除结果
     */
    @Override
    public boolean removeByProductId(Integer productId, int type) {
        LambdaQueryWrapper<ProductAttrValue> lambdaQW = Wrappers.lambdaQuery();
        lambdaQW.eq(ProductAttrValue::getProductId, productId).eq(ProductAttrValue::getType, type);
        return dao.delete(lambdaQW) > 0;
    }

    /**
     * 根据商品id和attrId获取规格属性
     *
     * @param productId     商品id
     * @param attrId        属性id
     * @param type          商品类型
     * @param marketingType 营销类型
     * @return 商品属性集合
     */
    @Override
    public ProductAttrValue getByProductIdAndAttrId(Integer productId, Integer attrId, Integer type, Integer marketingType) {
        LambdaQueryWrapper<ProductAttrValue> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductAttrValue::getProductId, productId);
        lqw.eq(ProductAttrValue::getType, type);
        lqw.eq(ProductAttrValue::getMarketingType, marketingType);
        lqw.eq(ProductAttrValue::getId, attrId);
        lqw.eq(ProductAttrValue::getIsDel, false);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }

    /**
     * 根据id、类型查询
     *
     * @param id   ID
     * @param type 类型
     * @return ProductAttrValue
     */
    @Override
    public ProductAttrValue getByIdAndProductIdAndType(Integer id, Integer productId, Integer type) {
        LambdaQueryWrapper<ProductAttrValue> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductAttrValue::getId, id);
        lqw.eq(ProductAttrValue::getProductId, productId);
        lqw.eq(ProductAttrValue::getType, type);
        lqw.eq(ProductAttrValue::getIsDel, false);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }

    /**
     * 根据id、类型查询
     *
     * @param id            ID
     * @param type          类型
     * @param marketingType 营销类型
     * @return ProductAttrValue
     */
    @Override
    public ProductAttrValue getByIdAndProductIdAndType(Integer id, Integer productId, Integer type, Integer marketingType) {
        LambdaQueryWrapper<ProductAttrValue> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductAttrValue::getId, id);
        lqw.eq(ProductAttrValue::getProductId, productId);
        lqw.eq(ProductAttrValue::getType, type);
        lqw.eq(ProductAttrValue::getMarketingType, marketingType);
        lqw.eq(ProductAttrValue::getIsDel, false);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }

    /**
     * 添加(退货)/扣减库存
     *
     * @param id            商品属性规格id
     * @param num           数量
     * @param operationType 类型：add—添加，sub—扣减，refund-退款添加库存
     * @param type          活动类型 0=商品
     * @return Boolean
     */
    @Override
    public Boolean operationStock(Integer id, Integer num, String operationType, Integer type, Integer version) {
        UpdateWrapper<ProductAttrValue> updateWrapper = new UpdateWrapper<>();
        if (operationType.equals(Constants.OPERATION_TYPE_QUICK_ADD)) {
            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
//            if (type > 0 && type < 5) {
//                updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
//            }
        }
        if (operationType.equals(Constants.OPERATION_TYPE_ADD)) {
            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
//            if (type > 0 && type < 5) {
//                updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
//            }
        }
        if (operationType.equals(Constants.OPERATION_TYPE_SUBTRACT)) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
//            if (type > 0 && type < 4) {
//                updateWrapper.setSql(StrUtil.format("quota = quota - {}", num));
//                // 扣减时加乐观锁保证库存不为负
//                updateWrapper.last(StrUtil.format("and (quota - {} >= 0)", num));
//            } else {// 普通商品或者视频号商品
//                // 扣减时加乐观锁保证库存不为负
//                updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
//            }
            updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
        }
        if (operationType.equals(Constants.OPERATION_TYPE_ACTIVITY_CREATE)) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            // 扣减时加乐观锁保证库存不为负
            updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
        }
        if (operationType.equals(Constants.OPERATION_TYPE_DELETE)) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
        }

        updateWrapper.setSql("version = version + 1");
        updateWrapper.eq("id", id);
        updateWrapper.eq("type", type);
        updateWrapper.eq("version", version);
        boolean update = update(updateWrapper);
        if (!update) {
            throw new CrmebException("更新商品attrValue失败，attrValueId = " + id);
        }
        return update;
    }

    /**
     * 添加/扣减库存
     *
     * @param id            商品属性规格id
     * @param num           数量
     * @param operationType 类型：add—添加，sub—扣减
     * @param type          基础类型：0=普通商品,1-积分商品,2-虚拟商品,4=视频号,5-云盘商品,6-卡密商品
     * @param marketingType 营销类型 1=秒杀
     */
    @Override
    public Boolean operationStock(Integer id, Integer num, String operationType, Integer type, Integer marketingType, Integer version) {
        UpdateWrapper<ProductAttrValue> updateWrapper = new UpdateWrapper<>();
        if (operationType.equals(Constants.OPERATION_TYPE_QUICK_ADD)) {
            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
            if (type > 0 && type < 5) {
                updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
            }
        }
        if (operationType.equals(Constants.OPERATION_TYPE_ADD)) {
            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
            if (marketingType > 0) {
                updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
            }
        }
        if (operationType.equals(Constants.OPERATION_TYPE_SUBTRACT)) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
            if (marketingType > 0) {
                updateWrapper.setSql(StrUtil.format("quota = quota - {}", num));
                // 扣减时加乐观锁保证库存不为负
                updateWrapper.last(StrUtil.format("and (quota - {} >= 0)", num));
            } else {// 普通商品或者视频号商品
                // 扣减时加乐观锁保证库存不为负
                updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
            }
        }
        if (operationType.equals(Constants.OPERATION_TYPE_ACTIVITY_CREATE)) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            // 扣减时加乐观锁保证库存不为负
            updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
        }
        if (operationType.equals(Constants.OPERATION_TYPE_DELETE)) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
        }

        updateWrapper.setSql("version = version + 1");
        updateWrapper.eq("id", id);
        updateWrapper.eq("type", type);
        updateWrapper.eq("marketing_type", marketingType);
        updateWrapper.eq("version", version);
        boolean update = update(updateWrapper);
        if (!update) {
            throw new CrmebException("更新商品attrValue失败，attrValueId = " + id);
        }
        return update;
    }

    /**
     * 删除商品规格属性值
     *
     * @param productId     商品id
     * @param type          商品类型
     * @param marketingType 营销类型
     * @return Boolean
     */
    @Override
    public Boolean deleteByProductIdAndType(Integer productId, Integer type, Integer marketingType) {
        LambdaUpdateWrapper<ProductAttrValue> luw = Wrappers.lambdaUpdate();
        luw.set(ProductAttrValue::getIsDel, true);
        luw.eq(ProductAttrValue::getProductId, productId);
        luw.eq(ProductAttrValue::getType, type);
        luw.eq(ProductAttrValue::getMarketingType, marketingType);
        return update(luw);
    }

    /**
     * 批量删除商品sku
     *
     * @param productIds    商品id
     * @param marketingType 营销类型
     * @return Boolean
     */
    @Override
    public Boolean batchDeleteByProductIdAndMarketingType(List<Integer> productIds, Integer marketingType) {
        LambdaUpdateWrapper<ProductAttrValue> luw = Wrappers.lambdaUpdate();
        luw.set(ProductAttrValue::getIsDel, true);
        luw.in(ProductAttrValue::getProductId, productIds);
        luw.eq(ProductAttrValue::getMarketingType, marketingType);
        return update(luw);
    }

    /**
     * 获取商品规格列表
     *
     * @param productId     商品id
     * @param type          商品类型
     * @param marketingType 营销类型
     * @param showSwitch    显示开关，true-只查询开启显示的sku
     * @return List
     */
    @Override
    public List<ProductAttrValue> getListByProductIdAndType(Integer productId, Integer type, Integer marketingType, Boolean showSwitch) {
        LambdaQueryWrapper<ProductAttrValue> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductAttrValue::getProductId, productId);
        lqw.eq(ProductAttrValue::getType, type);
        lqw.eq(ProductAttrValue::getMarketingType, marketingType);
        lqw.eq(ProductAttrValue::getIsDel, false);
        if (showSwitch) {
            lqw.eq(ProductAttrValue::getIsShow, 1);
        }
        return dao.selectList(lqw);
    }

    /**
     * 根据商品id和attrIdList获取列表集合
     *
     * @param productId     商品id
     * @param attrIdList    属性idList
     * @param type          商品类型
     * @param marketingType 营销类型
     * @return 商品属性集合
     */
    @Override
    public List<ProductAttrValue> getByProductIdAndAttrIdList(Integer productId, List<Integer> attrIdList, Integer type, Integer marketingType) {
        LambdaQueryWrapper<ProductAttrValue> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductAttrValue::getProductId, productId);
        lqw.eq(ProductAttrValue::getType, type);
        lqw.eq(ProductAttrValue::getMarketingType, marketingType);
        lqw.in(ProductAttrValue::getId, attrIdList);
        lqw.eq(ProductAttrValue::getIsDel, false);
        return dao.selectList(lqw);
    }

    /**
     * 更新商品佣金
     *
     * @param proId         商品ID
     * @param type          商品类型
     * @param marketingType 营销类型
     * @param brokerage     一级佣金
     * @param brokerageTwo  二级佣金
     */
    @Override
    public Boolean updateBrokerageByProductId(Integer proId, Integer type, Integer marketingType, Integer brokerage, Integer brokerageTwo) {
        LambdaUpdateWrapper<ProductAttrValue> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(ProductAttrValue::getBrokerage, brokerage);
        wrapper.set(ProductAttrValue::getBrokerageTwo, brokerageTwo);
        wrapper.eq(ProductAttrValue::getProductId, proId);
        wrapper.eq(ProductAttrValue::getType, type);
        wrapper.eq(ProductAttrValue::getMarketingType, marketingType);
        return update(wrapper);
    }

    @Override
    public Boolean deleteByMasterIdListAndMarktingType(List<Integer> skuIdList, Integer marketingType) {
        LambdaUpdateWrapper<ProductAttrValue> luw = Wrappers.lambdaUpdate();
        luw.set(ProductAttrValue::getIsDel, true);
        luw.in(ProductAttrValue::getMasterId, skuIdList);
        luw.eq(ProductAttrValue::getMarketingType, marketingType);
        return update(luw);
    }

    /**
     * 修改是否展示ai换衣图
     *
     * @param aiAttrVal
     */
    @Override
    public void updateByList(List<ProductAttrValue> aiAttrVal) {
        LambdaUpdateWrapper<ProductAttrValue> luw = Wrappers.lambdaUpdate();
        luw.set(ProductAttrValue::getIsShowAiClothesUrl, 1);
        luw.in(ProductAttrValue::getId, aiAttrVal.stream().map(m -> m.getId()).collect(Collectors.toList()));
        update(luw);
    }


    /**
     * 新增商品自动跑ai换衣图task任务
     */
    @Override
    public void productAiAutoCancel() {
        DateTime dateTime = DateUtil.offsetMinute(new Date(), -10);
        LambdaUpdateWrapper<ProductAttrValue> lqw = new LambdaUpdateWrapper<>();
        lqw.eq(ProductAttrValue::getIsShowAiClothesUrl, 1);
        lqw.isNotNull(ProductAttrValue::getAiClothesUrl);
        lqw.and(i -> i.isNull(ProductAttrValue::getAiManInitClothesUrl).or().isNull(ProductAttrValue::getAiWomanInitClothesUrl));
        lqw.le(ProductAttrValue::getCreateTime, dateTime);
        lqw.orderByDesc(ProductAttrValue::getId);
        List<ProductAttrValue> list = list(lqw);
        //初始化ai试穿图
        //提交任务到线程池异步执行
        //TODO Kenan
        ThreadUtil.execAsync(() -> {
            System.out.println("异步任务开始执行...");
            //查询模特url
            List<UserModelUrl> userModelUrlList = userModelUrlService.selectList();
            if (CollUtil.isNotEmpty(userModelUrlList)) {
                list.forEach(productAttrValue -> {
                    if (StrUtil.isBlank(productAttrValue.getAiManInitClothesUrl())) {
                        UserModelUrl userModelUrl = userModelUrlList.stream().filter(f -> f.getModelType() == 0).findFirst().get();
                        AiRequest a = new AiRequest()
                                .setId(productAttrValue.getId())
                                .setModelImgUrl(userModelUrl.getModelUrl());
                        productService.initializeAiImage(a, userModelUrl.getModelType(), productAttrValue.getAiClothesUrl(), true);

                    }
                    if (StrUtil.isBlank(productAttrValue.getAiWomanInitClothesUrl())) {
                        UserModelUrl userModelUrl = userModelUrlList.stream().filter(f -> f.getModelType() == 1).findFirst().get();
                        AiRequest a = new AiRequest()
                                .setId(productAttrValue.getId())
                                .setModelImgUrl(userModelUrl.getModelUrl());
                        productService.initializeAiImage(a, userModelUrl.getModelType(), productAttrValue.getAiClothesUrl(), true);
                    }

                });

            }
            System.out.println("异步任务完成！");
        });
        // 主线程继续执行其他逻辑
        System.out.println("主线程继续运行...");

    }


    /**
     * 根据id列表查询
     *
     * @param idList
     * @return
     */
    @Override
    public List<ProductAttrValue> getListByIdList(List<Integer> idList) {
        return dao.getListByIdList(idList);
    }


    /**
     * 重新生成ai试衣图
     *
     * @param againGenerateImageRequest
     * @param aiToken
     * @param flag
     * @return
     */
    @Override
    public List<String> sendAgainGenerateImage(AgainGenerateImageRequest againGenerateImageRequest, String aiToken, Integer flag) {
        ProductAttrValue productAttrValue = dao.selectById(againGenerateImageRequest.getProductAttrValueId());
        Product product = productService.getById(productAttrValue.getProductId());
        Integer categoryId = dao.selectCategoryIdByProductAttrValueId(againGenerateImageRequest.getProductAttrValueId());
        //查询出一级分类id的名称,根据名称判断跑男模特还是女模特
        String name = productCategoryDao.getNameByCategoryId(categoryId);
        if (StrUtil.isBlank(name)) {
            throw new CrmebException("该规格的分类id不对,请编辑正常后再来生成试衣图");
        }
        Integer modelType = "男装".equals(name) ? 0 : "女装".equals(name) ? 1 : 2;
        UserModelUrl userModelUrl = userModelUrlService.selectByModelType(modelType);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("background", systemAttachmentService.getCdnUrl() + "/" + userModelUrl.getModelUrl());
        jsonObject.put("garment_img", systemAttachmentService.getCdnUrl() + "/" + productAttrValue.getAiClothesUrl());
        jsonObject.put("category", product.getAiClothesType() == null ? "upper_body" : product.getAiClothesType());
        //提示词800字符
        jsonObject.put("garment_des", againGenerateImageRequest.getGarmentDes());
        jsonObject.put("is_checked", true);
        //是否裁剪图片
        jsonObject.put("is_checked_crop", true);
        //步数
        jsonObject.put("denoise_steps", againGenerateImageRequest.getDenoiseSteps());
        //是否随机true 随机
        jsonObject.put("is_randomize_seed", againGenerateImageRequest.getIsRandomizeSeed());
        //种子0随机 大于0就是1-2147483647
        jsonObject.put("seed", againGenerateImageRequest.getSeed());
        //生成图片的数量，最好1-4
        jsonObject.put("number_of_images", againGenerateImageRequest.getNumberOfImages());
        jsonObject.put("mod_id", userModelUrl == null ? "" : userModelUrl.getId().toString());
        //本地
        Map codeMap = restTemplateUtil.postJsonDataToObj("http://192.168.1.6:8000/api/v1/tryon/file", jsonObject, aiToken);
        //线上
//        Map codeMap = restTemplateUtil.postJsonDataToObj("http://106.53.113.177:8001/api/v1/tryon/file", jsonObject, aiToken);
        //本地
//        Map codeMap = restTemplateUtil.postJsonDataToObj("http://jykj.a1.luyouxia.net:26436/api/v1/tryon/file", jsonObject, aiToken);
        Integer code = (Integer) codeMap.get("code");
        if (401 == code) {
            String token = productService.aiLogin();
            flag += 1;
            if (flag > 30) {
                codeMap.put("message", "请求超时了，请稍后重试");
                throw new CrmebException("请求超时了，请稍后重试");
            }
            return sendAgainGenerateImage(againGenerateImageRequest, token, flag);
        } else if (200 == code) {
            String resultUrl = (String) codeMap.get("resultUrl");
            if (StrUtil.isNotBlank(resultUrl)) {
                String[] split = resultUrl.split(",");
                ArrayList<String> arrayList = ListUtil.toList(split);
                return arrayList;
            }
        }
        return new ArrayList<>();
    }


}

